﻿// SKNotes - a note taking and gathering tool
// Copyright (C) 2009  Stefan Kueng
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Reflection;

namespace SKNotes.Utilities
{
    class AccessInternals
    {
        public static object GetMembers(object objName, string propertyName)
        {
            Type objType = objName.GetType();
            FieldInfo fild = GetFieldInfo(objType, propertyName);
            if (fild == null)
            {
                throw new ArgumentException("There is no field '" +
                    propertyName + "' for type '" + objName.GetType().ToString() + "'.");
            }
            object test = fild.GetValue(objName);
            return fild.GetValue(objName);
        }

        public static void SetMembers(object objName, string propertyName, object aValue)
        {
            FieldInfo fld = GetFieldInfo(objName.GetType(), propertyName);
            if (fld == null)
            {
                throw new ArgumentException("There is no field '" +
                    propertyName + "' for type '" + objName.GetType().ToString() + "'.");
            }
            fld.SetValue(objName, aValue);
        }

        private static FieldInfo GetFieldInfo(Type objType, string propertyName)
        {
            FieldInfo fild = objType.GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);
            if (fild != null)
                return fild;
            if (objType.GetType() == typeof(object))
                return null;
            return GetFieldInfo(objType.BaseType, propertyName);
        }

        public static object RunInstanceMethod(object objInstance, string strMethod, object[] aobjParams)
        {
            BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.NonPublic;
            return RunMethod(strMethod, objInstance, aobjParams, eFlags);
        }

        private static object RunMethod(string strMethod, object objInstance, object[] aobjParams, BindingFlags eFlags)
        {
            Type t = objInstance.GetType();
            MethodInfo m = GetMethod(t, strMethod, eFlags);
            if (m == null)
            {
                throw new ArgumentException("There is no method '" +
                    strMethod + "' for type '" + t.ToString() + "'.");
            }

            object objRet = m.Invoke(objInstance, aobjParams);
            return objRet;


        }

        private static MethodInfo GetMethod(Type t, string strMethod, BindingFlags eFlags)
        {
            MethodInfo m = t.GetMethod(strMethod, eFlags);
            if (m != null)
                return m;
            if (t.GetType() == typeof(object))
                return null;
            return GetMethod(t.BaseType, strMethod, eFlags);

        }
    }
}
